package com.hundsun.cprs.yyt.service.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.enums.EnumBusinessCode;
import com.hundsun.cprs.yyt.common.exception.ServiceCodeException;
import com.hundsun.cprs.yyt.service.common.service.RemoteTradeFundService;
import com.hundsun.cprs.yyt.service.system.GeneratorClearingFileService;
import com.hundsun.cprs.yyt.service.system.domain.TradeDay;
import com.hundsun.cprs.yyt.service.system.dto.ClearingCenterMessageKey;
import com.hundsun.cprs.yyt.service.system.enums.EnumCloseTradeStatus;
import com.hundsun.cprs.yyt.service.system.enums.EnumOpenFlag;
import com.hundsun.cprs.yyt.service.system.enums.EnumOpenTradeStatus;
import com.hundsun.cprs.yyt.service.system.service.ClearingTradeService;
import com.hundsun.cprs.yyt.service.system.service.TradeDayService;
import com.hundsun.cprs.yyt.util.DateUtil;
import com.hundsun.cprs.yyt.util.HttpClientUtil;
import com.hundsun.cprs.yyt.util.StringUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class ClearingTradeServiceImpl extends BaseService implements ClearingTradeService {

    Logger logger = Logger.getLogger(ClearingTradeServiceImpl.class);

    String authorization;

    String bankProCode = "clearingCenter";

    String exchangeCode;//交易所编码

    String postUrl;//请求地址

    @Autowired
    private RemoteTradeFundService remoteTradeFundService;

    @Autowired
    private GeneratorClearingFileService generatorClearingFileService;

    @Autowired
    private TradeDayService tradeDayService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    @Transactional
    public void openTrade(Date tradeDate){
        try{
            //初始化资金参数
            intParamterFromFundSystem();
            //更改交易系统维护的开市状态
            updateClearingTradeStatus(tradeDate,EnumOpenTradeStatus.COMPLETED_OPEN.getCode(),"open","success");
            //发送开市消息
            sendMessage(EnumOpenFlag.OPEN_TRADE.getCode(),tradeDate);
        }catch (Exception e){
            //更改交易系统维护的开市状态
            updateClearingTradeStatus(tradeDate,EnumOpenTradeStatus.FAIL_OPEN.getCode(),"open",e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public void closeTrade(Date tradeDate) {
        try{
            //初始化资金参数
            intParamterFromFundSystem();
            //更改交易系统维护的闭市状态
            updateClearingTradeStatus(tradeDate,EnumCloseTradeStatus.COMPLETED_CLOSE.getCode(),"close","success");
            //生成清算中心文件
            generatorClearingFileService.generatorClearingFile(exchangeCode,authorization,postUrl,tradeDate);
            //发送闭市消息
            sendMessage(EnumOpenFlag.CLOSE_TRADE.getCode(),tradeDate);
        }catch (Exception e){
            //更改交易系统维护的闭市状态
            updateClearingTradeStatus(tradeDate,EnumCloseTradeStatus.FAIL_CLOSE.getCode(),"close",e.getMessage());
            throw e;
        }
    }

    protected Map<String,String> initParam(String keyCloseFlag,String exchangeCode,Date tradeDate){
        Map<String,String> paramMap = new HashMap<>();
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
        // 交易日期
        paramMap.put(ClearingCenterMessageKey.KEY_INIT_DATE, sdfDate.format(tradeDate));
        //交易所代码
        paramMap.put(ClearingCenterMessageKey.KEY_EXCHANGE_CODE,exchangeCode);
        //交易所市场编码||1-不区分|2-做市交易|3-挂牌交易|4-电子商城
        paramMap.put(ClearingCenterMessageKey.KEY_MARKET_TYPE,"1");
        //交易市场业务类型||1-不区分|2-大宗商品|3-金融资产|4-文化产权|5-邮币卡
        paramMap.put(ClearingCenterMessageKey.KEY_BIZ_TYPE,"1");
        //闭市标志：1-开市，0-闭市
        paramMap.put(ClearingCenterMessageKey.KEY_CLOSE_FLAG,keyCloseFlag);
        //下一个工作日  获取系统配置的下一清算日
        TradeDay tradeDay = tradeDayService.getNextClearingDay(tradeDate);
        if (tradeDay == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1034.getErrorNo(),EnumBusinessCode.BUSINESS_1034.getErrorInfo());
        }
        paramMap.put(ClearingCenterMessageKey.KEY_NEXT_WORKDAY, sdfDate.format(tradeDay.getDay()));

        //业务时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        paramMap.put(ClearingCenterMessageKey.KEY_BUSI_DATETIME,sdf.format(new Date()));

        paramMap.put("interfaceno", "update_third_party_calendar_info");
        paramMap.put("interfacename", "发送开闭市通知");

        return paramMap;
    }

    protected void intParamterFromFundSystem(){
        try{
            Map<String,String> configMap = remoteTradeFundService.getConfigInfoByBankChannel(bankProCode);
            authorization = HttpClientUtil.BEARER + configMap.get("access_token");
            exchangeCode = configMap.get("exchange_code");
            postUrl = configMap.get("postUrl");
        }catch (Exception e){
            logger.error("开闭市查询资金参数配置出错：" + e);
            throw e;
        }
    }

    protected void sendMessage(String keyCloseFlag,Date tradeDate){
        try{
            Map<String,String> paramMap = initParam(keyCloseFlag,exchangeCode,tradeDate);
            String responseStr = HttpClientUtil.sendPost(
                    postUrl+"update_third_party_calendar_info",
                    paramMap,
                    HttpClientUtil.CHARSET,
                    HttpClientUtil.CHARSET,
                    null,
                    authorization,
                    paramMap.get("interfacename"));
            JSONObject response = JSONObject.parseObject(responseStr);
            if (response.get("data")==null){
                throw new ServiceCodeException(responseStr);
            }
        }catch (ServiceCodeException e){
            logger.error("开闭市失败："+ e);
            throw e;
        }catch (IOException e){
            logger.error("开闭市失败："+ e);
            throw new ServiceCodeException(e.getMessage());
        }
    }

    //独立事务提交，不受主事务的影响
    public void updateClearingTradeStatus(Date date,String status,String type,String memo){
        DefaultTransactionDefinition defintion = new DefaultTransactionDefinition();
        defintion.setPropagationBehavior(Propagation.REQUIRES_NEW.value());
        defintion.setIsolationLevel(Isolation.READ_COMMITTED.value());
        TransactionStatus transactionStatus = transactionTemplate.getTransactionManager().getTransaction(defintion);
        try{
            TradeDay tradeDay = new TradeDay();
            tradeDay.setMemo(memo);
            if (type.equals("open")){
                tradeDay.setOpenTradeStatus(status);
                tradeDay.setCloseTradeStatus(null);
            }else{
                tradeDay.setOpenTradeStatus(null);
                tradeDay.setCloseTradeStatus(status);
            }
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            tradeDay.setDay(DateUtil.convertStringToDate(df.format(date)));
            tradeDayService.updateTradeStatus(tradeDay);
            transactionTemplate.getTransactionManager().commit(transactionStatus);

        }catch (ParseException e){
            transactionTemplate.getTransactionManager().rollback(transactionStatus);
            throw new ServiceCodeException(e.getMessage());
        }
    }

}
